package com.elite.groovy.callback

import com.elite.groovy.davco.clink.clinkAgentStatus
import com.elite.groovy.davco.clink.clinkCallControl
import com.elite.groovy.kh.KHDBConfig
import com.elite.groovy.kh.KHUtil
import com.elite.groovy.kh.LogToDB
import com.elite.groovy.util.EliteBean
import com.tinet.clink.core.client.Client
import com.tinet.clink.core.client.ClientConfiguration
import net.sf.json.JSONArray
import net.sf.json.JSONObject
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.jdbc.core.JdbcTemplate

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 * @projectName: Groovy
 * @package: com.elite.groovy.callback
 * @className: apiWoCallControl
 * @description: 手机端工单点击拨打客户电话AXB接口
 * @author: LiJT
 * @date: 2023-10-27 11:13
 * @version: 1.0
 */

public class apiWoCallControl implements ServiceBackInvoke {
    private static final Log log = LogFactory.getLog(apiWoCallControl.class);

    private static JdbcTemplate jt = null;
    private static JSONObject reJson = null;

    // 创建访问服务的client实例并初始化
    private static ClientConfiguration configuration = new ClientConfiguration("ea4478dba2ca33fc67fe0b1f43df5430", "5T5q9u1cNSB2234Gio8L");
    private static Client client = null;

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {

        long startTime = System.currentTimeMillis();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");

        reJson = JSONObject.fromObject("{\"code\":0,\"message\":\"WARN.\",\"value\":{}}");

        // 调用IP过滤
        if (KHDBConfig.getParam(eliteBean, "#APIIP").equals("1") && !KHUtil.getRemoteHost(request)) {
            reJson.put("message", "API被非法IP调用-Request Not Allow!");
            log.warn(reJson.toString());
            return reJson.toString();
        }

        // 调用Method过滤
        String getMethod = request.getMethod();
        log.debug("HTTP请求调用类型 getMethod:" + getMethod);
        if (!getMethod.equals("GET")) {
            reJson.put("message", "HTTP请求调用类型错误，接口调用失败：" + getMethod);
            log.warn(reJson.toString());
            return reJson.toString();
        }

        // 获取所有Header
        Map<String, String> mapHeader = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            log.debug("Call Header-" + key + ":" + value);

            mapHeader.put(key, value);
        }

        // 获取所有参数名
        Map<String, String> mapParams = new HashMap<String, String>();
        Enumeration ep = request.getParameterNames();
        while (ep.hasMoreElements()) {
            String key = (String) ep.nextElement();
            String value = request.getParameter(key);
            log.debug("Call Parameter-" + key + ":" + value);
            mapParams.put(key, value);

        }

        // 获取调用数据
        String Syncpram = request.getQueryString();
        log.info("接收调用GET参数信息：" + Syncpram);

        // 调用操作类型
        String op_type = "/";

        try {
            // 获取数据源List<Map<String, Object>>
            jt = new JdbcTemplate(eliteBean.getDataSource());

            configuration.setScheme("http");
            configuration.setHost("api-sh.clink.cn");
            client = new Client(configuration);

            /* 类型
            CALL 外呼
            CALLEND 挂机
            */

            op_type = request.getParameter("op_type");

            if(op_type.equals("clink_callend")){

                try {

                    String cdr_cno = request.getParameter("cdr_cno");

                    // 获取配置的可用外呼池
                    String CnosArr = KHDBConfig.getParamConfig(eliteBean, "WO_CALL_AGENTS");
                    CnosArr = KHUtil.isNull(CnosArr) ? "2009;2010;2011" : CnosArr;
                    String[] Cnos = CnosArr.split(";");
                    for (int i = 0; i < Cnos.length; i++) {
                        if(Cnos[i] == cdr_cno){

                            log.warn("工号通话结束下线:" + cdr_cno);
                            clinkCallControl.doOffline(client, request.getParameter("cdr_cno"));
                            return "succ";
                        }
                    }
                } catch (Exception e1) {
                    log.warn("工号下线异常:" + e1.getMessage());
                }
            }

            if (op_type.equals("CALL")) {
                reJson = doMakeCall(eliteBean, mapParams);

            } else if (op_type.equals("CALLEND")) {
                reJson = doUnlink(eliteBean, mapParams);

            } else {
                reJson.put("message", "暂不支持的调用操作类型 op_type=" + op_type);
                log.warn("暂不支持的操作类型 处理结果:" + reJson.toString());

            }

        } catch (Exception e) {
            reJson.put("message", "工单离线外呼接口 处理错误：" + e.getMessage());
            log.error("工单离线外呼接口 处理错误", e);

        } finally {
            LogToDB.toDB(eliteBean, "dataSource", "工单离线外呼接口", "apiWoCallControl", Syncpram, reJson.toString(), String.valueOf((System.currentTimeMillis() - startTime)), op_type);
        }

        log.debug("工单离线外呼接口 调用处理时长(毫秒):" + (System.currentTimeMillis() - startTime) + " 处理结果:" + reJson.toString());

        return reJson.toString();

    }

    // 外呼操作
    public static JSONObject doMakeCall(EliteBean eliteBean, Map<String, String> mapParams) throws Exception {
        JSONObject reJsonP = JSONObject.fromObject(reJson.toString());

        String log_Guid = "WOCALL_" + KHUtil.getRandomString(29).toUpperCase();
        String Status = "0";

        String wo_Guid = mapParams.get("wo_guid");
        String rolegroup_ID = mapParams.get("rolegroup_id");
        String staff_ID = mapParams.get("staff_id");
        String cno_Tel = mapParams.get("cno_tel");
        String cust_Tel = mapParams.get("cust_tel");

        // 获取配置的可用外呼池
        String CnosArr = KHDBConfig.getParamConfig(eliteBean, "WO_CALL_AGENTS");
        CnosArr = KHUtil.isNull(CnosArr) ? "2009;2010;2011" : CnosArr;
        String[] Cnos = CnosArr.split(";");

        // 获取外呼池工号状态
        String clinkResult = clinkAgentStatus.getAgentStatus(client, Cnos);
        log.debug("获取外呼池工号状态结果:" + clinkResult);

        // 找到一个可用坐席离线或上线时间较久未打电话
        JSONArray agentsArr = JSONObject.fromObject(clinkResult).getJSONArray("agentStatus");

        String cur_Cno = "";
        for (int i = 0; i < agentsArr.size(); i++) {
            JSONObject agentJson = agentsArr.getJSONObject(i);
            String cno = agentJson.getString("cno");
            String bindType = agentJson.getString("bindType");
            String bindTel = agentJson.getString("bindTel");
            String customerNumber = agentJson.getString("customerNumber");
            String loginDuration = agentJson.getString("loginDuration");
            String agentStatus = agentJson.getString("agentStatus");
            String stateDuration = agentJson.getString("stateDuration");

            if (agentStatus.equals("离线")) {
                cur_Cno = cno;
                break;
            }
        }

        // 如果离线的没有找到则找忙碌时长最长的
        if (KHUtil.isNull(cur_Cno)) {
            log.debug("如果离线的没有找到则找忙碌时长最长坐席");
            int curStateDuration = 0;
            for (int i = 0; i < agentsArr.size(); i++) {
                JSONObject agentJson = agentsArr.getJSONObject(i);
                String cno = agentJson.getString("cno");
                String bindType = agentJson.getString("bindType");
                String bindTel = agentJson.getString("bindTel");
                String agentStatus = agentJson.getString("agentStatus");
                String stateDuration = agentJson.getString("stateDuration");

                if (curStateDuration < Integer.valueOf(stateDuration) && Integer.valueOf(stateDuration) > 10 && agentStatus.equals("置忙")) {
                    log.debug("找忙碌时长最长工号:" + cno + " 置忙时长:" + stateDuration + " 已找到最长时长:" + curStateDuration);
                    curStateDuration = Integer.valueOf(stateDuration);
                    cur_Cno = cno;
                }
            }
            if (!KHUtil.isNull(cur_Cno)) {
                // 找到的置忙账号要先做下离线操作
                try {
                    clinkCallControl.doOffline(client, cur_Cno);
                } catch (Exception e1) {
                    log.warn("置忙工号下线异常:" + e1.getMessage());
                }
            }
        }


        if (KHUtil.isNull(cur_Cno)) {
            Status = "-1";
            reJsonP.put("message", "暂未找到空闲线路,请稍后再试");
            reJsonP.put("value", JSONObject.fromObject(clinkResult));
            log.warn("暂不支持的操作类型 处理结果:" + reJsonP.toString());

        } else {

            try {

                clinkCallControl.doOnline(client, cur_Cno, cno_Tel);
            } catch (Exception e) {
                String ExceptionMSG = e.getMessage();
                log.warn("工号上线异常:" + ExceptionMSG);

                String err_Cno = ExceptionMSG.split("-")[1].substring(0, 4);
                try {
                    try {
                        clinkCallControl.doOffline(client, err_Cno);
                    } catch (Exception e1) {
                        log.warn("工号下线异常:" + e1.getMessage());
                    }

                    try {
                        clinkCallControl.unbindClientTel(client, err_Cno);
                    } catch (Exception e1) {
                        log.warn("工号解绑异常:" + e1.getMessage());
                    }

                    clinkCallControl.doOnline(client, cur_Cno, cno_Tel);

                } catch (Exception e1) {
                    log.warn("工号解绑异常:" + e1.getMessage());
                }
            }

            clinkCallControl.doCallout(client, cur_Cno, cust_Tel);

            Status = "1";
            reJsonP.put("code", Integer.valueOf(Status));
            reJsonP.put("message", "外呼成功");
            reJsonP.put("value", JSONObject.fromObject("{\"cno\":\"" + cur_Cno + "\",\"call_id\":\"" + log_Guid + "\"}"));
        }

        // 将数据写入表
        String insertSQL = "Insert Into Dg_Wo_Call_Lists (Rec_Guid, Wo_Guid, Rolegroup_Id, Staff_Id, Cno_Tel, Cust_Tel, use_cno, Status, Update_By, Update_Time) Values (?, ?, ?, ?, ?, ?, ?, ?, ?, Now())";
        int num = jt.update(insertSQL, log_Guid, wo_Guid, rolegroup_ID, staff_ID, cno_Tel, cust_Tel, cur_Cno, Status, staff_ID);
        log.debug("工单离线外呼接口 将数据写入表-Dg_Wo_Call_Lists(" + wo_Guid + ") 数量：" + num);

        return reJsonP;

    }

    // 挂断操作
    public static JSONObject doUnlink(EliteBean eliteBean, Map<String, String> mapParams) throws Exception {
        JSONObject reJsonP = JSONObject.fromObject(reJson.toString());

        String log_Guid = "";
        String Status = "0";
        String Is_Callend_Status = "/";

        String wo_Guid = mapParams.get("wo_guid");
        String rolegroup_ID = mapParams.get("rolegroup_id");
        String staff_ID = mapParams.get("staff_id");

        // 客户的近期订单
        String selectUse_Cno = "Select Rec_Guid, Use_Cno From Dg_Wo_Call_Lists Where Wo_Guid = ? And Rolegroup_Id = ? And Staff_Id = ? And Status = 1 Order By Update_Time Desc Limit 1";
        List<Map<String, Object>> selectUseList = jt.queryForList(selectUse_Cno, wo_Guid, rolegroup_ID, staff_ID);
        log.debug("挂断操作 获取上次使用的工号：" + selectUseList.toString());

        if (selectUseList.size() > 0) {
            log_Guid = selectUseList.get(0).get("Rec_Guid").toString();
            String cur_Cno = selectUseList.get(0).get("Use_Cno").toString();
            try {
                clinkCallControl.doUnlink(client, cur_Cno);
                Status = "1";
                Is_Callend_Status = "SUCC";
            } catch (Exception e1) {
                log.warn("工号挂断异常:" + e1.getMessage());
                Status = "-1";
                Is_Callend_Status = e1.getMessage();

            }

            // 将数据写入表
            String updateSQL = "Update Dg_Wo_Call_Lists Set Is_Callend = ?, Is_Callend_Time = Now(), Is_Callend_Status = ? Where Rec_Guid = ?";
            int num = jt.update(updateSQL, Status, Is_Callend_Status, log_Guid);
            log.debug("工单离线外呼接口 将数据挂断更新表-Dg_Wo_Call_Lists(" + wo_Guid + ") 数量：" + num);

            reJsonP.put("code", Integer.valueOf(Status));
            reJsonP.put("message", Is_Callend_Status);
            reJsonP.put("value", JSONObject.fromObject("{\"cno\":\"" + cur_Cno + "\",\"call_id\":\"" + log_Guid + "\"}"));

        } else {
            reJsonP.put("message", "暂未找到使用的工号");
            log.warn("暂未找到次使用的工号 处理结果:" + reJsonP.toString());

        }

        return reJsonP;

    }
}
